#!/usr/bin/perl
#
# fastsq-shuffle.pl
# Randomize reads in a fastq (or pair of fastq) file.
#
# Copyright (C) 2014 Shawn Driscoll, sdriscoll@salk.edu
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#

use strict;
use List::Util 'shuffle';

die "Usage: fastq-shuffle.pl <fastq> [<fastq_mate>]" unless (scalar @ARGV) >= 1;

# -- variables

my ($fcur, $flast);
my (@reads, @sreads);
my $fname = shift @ARGV;
my $fmate = "";
my $fout = "fqshuf";
my $fout_mate = "";
my $pe = 0;
my $n;
my $line = 0;

# -- get it

if((scalar @ARGV) > 0) {
	$fmate = shift @ARGV;
	$pe = 1;
	$fout_mate = $fout . ".2.fq";
	$fout .= ".1.fq";
}
else {
	$fout .= ".fq";
}

# open file, read lines, record positions of reads in an array

open IN, "<", $fname or die($!);
$flast = 0;
$line = 0;
while(<IN>) {
	$line++;
	$fcur = tell IN;
	if($line==1) {
		push(@reads, $flast);
	}
	
	$line = 0 if $line == 4;
	$flast = $fcur;
}

# -- randomize positions

@sreads = shuffle(@reads);

# -- loop through randomized positions and print them back out

open OUT , ">", $fout;

foreach $fcur (@sreads) {
	seek IN, $fcur, 0;

	$n = 0;
	while(<IN>) {
		print OUT $_;
		$n++;
		last if $n==4;
	}	
}

close IN;
close OUT;

if($pe) {
	# open mate file and print out using the same shuffle
	open IN, "<", $fmate;
	open OUT, ">", $fout_mate;

	foreach $fcur (@sreads) {
		seek IN, $fcur, 0;

		$n = 0;
		while(<IN>) {
			print OUT $_;
			$n++;
			last if $n==4;
		}	
	}

	close IN;
	close OUT;

}
